Приглашаем посетить
Чернышевский (chernyshevskiy.lit-info.ru)

Creating CSS-Based Menus

Previous Page
Table of Contents
Next Page

Creating CSS-Based Menus

When I approach the problem of creating drop-down menus from list markup, I want to be able to take a list, with nested lists for the drop-downs, and have it work without needing to add any additional markupjust vanilla XHTML list markup and my CSS. What follows is how to create CSS drop-down menus from "ID-and-class-free" lists. All that's required is contexta surrounding div with an ID, so the correct CSS styles are applied to the list within. Certainly, once you have the CSS, these drop-down menus are very simple to incorporate in a site.

Creating CSS-Based Menus

You can download the CSS from the Stylin' site (www.bbd.com/stylin).


Your first step toward drop-down menus is to create the horizontal menu from which they dropa useful element in its own right.

Horizontal Navigation Components

Drop-down menus contain subcategories, which fall from each main category in a horizontal list. Drop-down menus are more flexible and space-efficient than vertical menus. Traditionally, drop-down menus have involved JavaScript, and often lots of it. Each drop-down menu required its own chunk of code, which was complex to modify or to develop as part of a dynamic site where such navigation would be expected to automatically reflect changes to site organization. With CSS, you can greatly simplify the creation of menus because the only markup that is required is lists, and one relatively small piece of CSS code can control the behavior of numerous menus without additional code being required as items are added to the menus.

So let's take a look at these advantages in action by first creating a horizontal navigation element, and then adding drop-down subcategories (Figure 7.11).

Figure 7.11. Here's a basic horizontal navigation element.

Creating CSS-Based Menus


This component is based on a simple list inside a div, like this

<div id="listmenu">
 <ul>
  <li><a href="#">Customers</a></li>
  <li><a href="#">Members</a></li>
  <li><a href="#">Dealers</a></li>
  <li><a href="#">Distributors</a></li>
  </ul>
</div>

But to get to the horizontal menu shown in Figure 7.11, we have to start more simply (Figure 7.12).

Figure 7.12. Here's the humble beginning of our horizontal drop-down menu.

Creating CSS-Based Menus


Start with some simple styles for the div; draw a line on its top and bottom edge, set its font size and the color of its background, and use a top-margin to push it away from the top of the browser.

Here's the markup

<style type="text/css">
body {font:1em verdana, arial, sans-serif;}
* {margin:0; padding:0;}
div#listmenu {
   width:100%;        <-- a
   border-top:1px solid #069;        <-- b
   border-bottom:1px solid #069;        <-- c
   font-size:.8em;        <-- d
   background-color:#CCF;        <-- e
   margin-top:20px;        <-- f
   }
</style>

(a)Makes the div full width

(b)Draws line on top edge of div

(c)Draws line on bottom edge of div

(d)Set font-size here

(e)Colors the div

(f)Temporarypushes the div away from the top of the browser for clarity in this example

The unstyled list is stacked by default, so the next thing we need to do is get it to lay out horizontally by floating the list elements (Figure 7.13). Let's move the list over from the left edge of the div and color the background of the list items while we're at it.

div#listmenu ul {margin:0 0 0 30px;        <-- a
   }
div#listmenu li {
   float:left;        <-- b
   background-color:#FFA;        <-- c
   }

(a)Indents ul from edge of container

(b)Causes the list to align horizontally instead of stack

(c)Sets the background of the menu items

Figure 7.13. Now your list is horizontal.

Creating CSS-Based Menus


Note that the div immediately snaps shut (although you won't see this in Internet Explorer) because the W3C recommendations state that floats are supposed to be able to hang outside of containing elements. Because there are only floats in this div, the div effectively has no content to enclose, so it has no height.

To fix this problem, remove the bullets of the list (which were off the edge of the screen in Figure 7.12), and start styling the links.

A simple way to get an element to enclose floated elements is to float it as well, like this

div#listmenu {
   width:100%;        <-- a
   float:left;        <-- b
   border-top:1px solid #069;        <-- c
   border-bottom:1px solid #069;        <-- d
   font-size:.8em;
   background-color:#CCF;        <-- e
   margin-top:20px;        <-- f
   }
div#listmenu ul {margin:0 0 0 30px;        <-- g
   }
div#listmenu li {
   float:left;        <-- h
   list-style-type:none;        <-- i
   background-color:#FFA;        <-- j
   }
div#listmenu a {
   text-decoration:none;        <-- k
   color:#069;        <-- l
   }
div#listmenu a:hover {
   color:#F33;        <-- m
   }

(a)Makes the div full width

(b)Makes the div enclose the list

(c)Draws line on top edge of div

(d)Draws line on bottom edge of div

(e)Colors the div

(f)Pushes the div away from the top of the browser for clarity here

(g)Indents ul from edge of container

(h)Causes the list to align horizontally

(i)Removes the bullet off list items

(j)Sets the background of the menu items

(k)Removes the underlining of the link

(l)Sets the type color

(m)Sets the type rollover color

Now the div opens up to enclose the floated list items.

The links are now styled so that they are blue in their normal state, and red when hovered over (Figure 7.14).

Figure 7.14. Links now turn red when the user rolls the pointer over them.

Creating CSS-Based Menus


Although we now get a nice rollover effect on the link, there is no visual separation between the list items. A few new styles take care of that

div#listmenu li {
   float:left;        <-- a
   list-style-type:none;        <-- b
   background-color:#FFA;        <-- c
   padding:0 6px;        <-- d
   border-right:1px solid #069;        <-- e
   }
div#listmenu li:first-child {
   border-left:1px solid #069;        <-- f
   }
   div#listmenu a {
   text-decoration:none;        <-- g
   color:#069;        <-- h
   background:#DDD;        <-- i
   }
div#listmenu a:hover {
   color:#F33;
   }

(a)Causes the list to align horizontally

(b)Removes the bullet off list items

(c)Sets the background of menu items

(d)Space on sides of menu item's text

(e)Creates dividing lines

(f)The first vertical line on the menu

(g)Removes the link underlining

(h)Sets the type color

(i)Temporarily shows hot area of link

The latest version of your link list is shown in Figure 7.15.

Figure 7.15. List items are now nicely separated.

Creating CSS-Based Menus


To create the dividing lines, in the preceding code, we first added a right border to each link, and that's four lines done. To create the very first dividing line, we used the :first-child pseudo-class to add a left border to the first list item. Because Internet Explorer for Windows does not recognize the :first-child pseudo-class, a bit later, you'll use a hack to fix this.

I've temporarily colored the backgrounds of the links gray so that you can see that they do not fill the entire list item space. This is a problem, because if you move the mouse into a yellow area, the link does not respond, as illustrated in Figure 7.15. You have to get onto the gray area of the link itself for the link to change color. What you want to do is make the link fill the list item space.

The problem is that links are inline elements that do not take width, height, or padding settings, so to provide settings to make a link fill its list item, you need to convert it to a block element. Then you can move the padding off the list item and onto the link; it then fills the list item and the whole area is "hot." Now modify your markup to look like this

div#listmenu li {
   float:left;
   list-style-type:none;
   background-color:#FFA;
   border-right:1px solid #069;
   }
div#listmenu li:first-child {
   border-left:1px solid #069;
   }
   div#listmenu a {
   padding:0 6px;        <-- a
   text-decoration:none;
   color:#069;
   background:#DDD;
   }
div#listmenu a:hover {
   color:#F33;
   }

(a)Creates space each side of menu item's text

Now the link fills the list item and moving the mouse into any part of it causes the link to change color (Figure 7.16).

Figure 7.16. List items are now nicely separated.

Creating CSS-Based Menus


All that you have to do now is take the temporary gray color off the link so the yellow background color of the list item is visible again, and have that background change color when it's rolled over by adding a :hover pseudo-class for the list items

div#listmenu li:hover {
   background-color:#FFF;        <-- a
   }
div#listmenu a {
   padding:0 6px;
   text-decoration:none;
   color:#069;
   }
div#listmenu a:hover {
   color:#F33;
   }

(a)Sets the background of the menu items

which looks like Figure 7.17.

Figure 7.17. Now your background changes color when the user points to it.

Creating CSS-Based Menus


Mousing onto any part of the list item causes the color of the list item to change color, except, yet again, in Internet Explorer for Windows.

Internet Explorer for Windows can only respond to the :hover pseudo-class when it is on a link, whereas more compliant browsers can provide a hover response on any elementin this case a list item. So although we have finished writing some solid CSS for this component, we must now do two more things to help poor old Internet Explorer for Windowsget Internet Explorer for Windows to display the first vertical line and get it to respond to the hover on the list item.

First add the vertical line to the left of the first list item. We can use the star hack to provide some CSS that is only read by Internet Explorer for Windows.

Up to now, we have only used the ul element to provide a left margin from which to indent the list from the left edge of the div. Because it only contains floated elements (the list items), it is tight closed in the same the div that was at the beginning of this exercise. Adding a temporary border like this

div#listmenu ul {margin:0 0 0 30px;        <-- a
   border: 1px solid #000;}

(a)Indents ul from edge of container

displays Figure 7.18.

Figure 7.18. The bottom edge of the ul element touches the top edge and is visible to the right of the yellow li elements.

Creating CSS-Based Menus


What we need to do is make the ul enclose the list items by floating it, like this

* html div#listmenu ul {
float:left;        <-- a
}

(a)Makes the ul wrap the li's

which results in Figure 7.19.

Figure 7.19. Now the ul encloses the list items.

Creating CSS-Based Menus


Now add a left border to take the place of the missing list item border, remove the temporary solid border, and add a blue line on just the left edge. (Note that one rather strange side effect of floating this element is that the indent from the edge of the div has doubled, and so you'll adjust for that also.) Here's the code

* html div#listmenu ul {
   float:left;        <-- a
   border-left:1px solid #000;        <-- b
   margin-left:15px;        <-- c
   }
* html a {display:block;}        <-- d

(a)Makes the ul wrap the li's

(b)Adds the rightmost vertical line to the ul

(c)IE doubles the given value above

(d)Makes IE 5 and 5.5 accept the padding on the link

Figure 7.20. The left line now displays in Internet Explorer for Windows, but the background doesn't produce a hover effect.

Creating CSS-Based Menus


Now that the left line shows up in Internet Explorer, we need to make the hover on the list items work.

The Hover Behavior for Internet Explorer

Creating CSS-Based Menus

A behavior is an imported file that adds functionality to a browser.


Before CSS2, only links could provide a response to being hovered over. Using the :hover pseudo-class on a selector enables you to define a response when an item is rolled over; for example, here's the CSS for a div with a blue background that turns red when the div is hovered over

div#respond {background-color:blue;}
div#respond:hover {background-color:red;}

It's that easy, although Internet Explorer doesn't produce a hover effect for any selector except a, a link. Fortunately, a very smart programmer, Peter Nederlof, came up with an Internet Explorer behavior that solves this problem. The file is called csshover.htc and you can download it from www.xs4all.nl/~peterned/hovercraft.html. Here's how you add it to the CSS

body {font:1em verdana, arial, sans-serif; behavior:url(css/csshover.htc);}

In this case, we created a new folder called css in the same folder as the files for this example and put the csshover.htc file in that new folder. If you decide to put the file in a different location, you will need to modify the URL.

With the csshover.htc file associated with your file in this way, Internet Explorer can respond to hovers. Now, across all of the target browsers, except Internet Explorer 5 for Mac, the background of the list item turns white when it is hovered over.

Our horizontal menu is complete.

Here's the complete code

body {font-family: verdana, arial, sans-serif; font-weight:100%; behavior:url(css/csshover
Creating CSS-Based Menus.htc);}
* {margin:0; padding:0;}        <-- a
div#listmenu {
   width:100%;        <-- b
   float:left;        <-- c
   border-top:1px solid #069;        <-- d
   border-bottom:1px solid #069;        <-- e
   font-size:.8em;
   background-color:#CCF;        <-- f
   margin-top:20px;        <-- g
   }
div#listmenu ul {margin:0 0 0 30px;        <-- h
   }
div#listmenu li {
   float:left;        <-- i
   list-style-type:none;        <-- j
   background-color:#FFA;        <-- k
   border-right:1px solid #069;        <-- l
   }
div#listmenu li:first-child {
   border-left:1px solid #069;        <-- m
   }
div#listmenu li:hover {
   background-color:#FFF;        <-- n
   }
div#listmenu a {
   padding:0 6px;        <-- o
   text-decoration:none;        <-- p
   color:#069;        <-- q
   }
div#listmenu a:hover {
   color:#F33;
   }        <-- r
* html div#listmenu ul {        <-- s
   float:left;        <-- t
   border-left:1px solid #000;        <-- u
   margin-left:15px;        <-- v
   }        <-- w

(a)The horizontal menu starts here

(b)Makes the div full width

(c)Makes the div enclose the list

(d)Draws line on top edge of div

(e)Draws line on bottom edge of div

(f)Colors the div

(g)Pushes the div away from the top of the browser for clarity in this example

(h)Indents ul from edge of container

(i)Indents ul from edge of container

(j)Removes the bullet off list items

(k)Sets background of the menu items

(l)Creates dividing lines

(m)The first vertical line on the menu

(n)Sets the background of the menu items

(o)Creates space each side of menu item's text

(p)Removes the link underlining

(q)Sets the type color

(r)The horizontal menu ends here

(s)Hack for IE so the menu has a vertical line on the left

(t)Makes the ul wrap the li's

(u)Adds the rightmost menu vertical line to the ul

(v)IE doubles the given value above

(w)End of hack zone

    Previous Page
    Table of Contents
    Next Page